<template>
  <view
    class="tn-popup"
    :class="[popupClass]"
    :style="popupStyle"
    hover-stop-propagation
  >
    <tn-overlay :show="mask && visible" :opacity="transparentMask ? 0 : undefined" :z-index="maskZIndex" @click="closePopup('mask')"></tn-overlay>
    <!-- 弹框内容 -->
    <view
      class="tn-popup__content"
      :class="[popupContentClass]"
      :style="popupContentStyle"
    >
      <!-- 内容 -->
      <!-- <view class="tn-popup__data">
        <slot></slot>
      </view> -->
      <slot></slot>
      <!-- 关闭按钮 -->
      <view
        v-if="closeIcon"
        class="tn-popup__close"
        :class="[popupCloseBtnClass]"
        :style="popupCloseBtnStyle"
        @tap.stop="closePopup"
      >
        <tn-icon :icon="closeIcon"></tn-icon>
      </view>
    </view>
  </view>
</template>

<script lang="ts" setup>
import { popupProps, popupEmits } from '../../../types/tn-popup'
import { ColorInfo } from '../../../types/tuniao-ui'
import { UPDATE_MODEL_EVENT } from '../../../constants'
import { computed, CSSProperties, ref, watch } from 'vue'
import useComponentColor from '../../../libs/hooks/useComponentColor'
import { handleValueWithUnit, hump2str } from '../../../utils'
import TnOverlay from '../../tn-overlay/src/Overlay.vue'
import TnIcon from '../../tn-icon/src/Icon.vue'

const props = defineProps(popupProps)
const emits = defineEmits(popupEmits)

const { splitColorInfo } = useComponentColor()

// 解析背景颜色
const bgColor = computed<ColorInfo>(() => {
  return splitColorInfo('bg', props?.bgColor || '')
})
// 解析关闭图标颜色
const closeIconColor = computed<ColorInfo>(() => {
  return splitColorInfo('color', props?.closeIconColor || '')
})

// popup容器样式
const popupStyle = computed<CSSProperties>(() => {
  let style: CSSProperties = {}
  if (typeof props?.zIndex !== 'undefined') style.zIndex = Number(props.zIndex)
  return Object.assign(style, props?.customStyle || {})
})
// popup内容样式
const popupContentStyle = computed<CSSProperties>(() => {
  let style: CSSProperties = {}
  if (bgColor.value.type === 'style') style.backgroundColor = bgColor.value.value
  if (typeof props?.zIndex !== 'undefined') style.zIndex = Number(props.zIndex)
  if (props.mode === 'left' || props.mode === 'right') {
    style.top = 0
    style.bottom = 0
    if (typeof props?.width !== 'undefined') style.width = handleValueWithUnit(props.width)
    if (props.mode === 'left') {
      style.transform = `translateX(${visible.value ? '0%' : '-100%'})`
      style.left = 0
    } else {
      style.transform = `translateX(${visible.value ? '0%' : '100%'})`
      style.right = 0
    }
  } else if (props.mode === 'top' || props.mode === 'bottom') {
    style.left = 0
    style.right = 0
    if (typeof props?.height !== 'undefined') style.height = handleValueWithUnit(props.height)
    if (props.mode === 'top') {
      style.transform = `translateY(${visible.value ? '0%' : '-100%'})`
      style.top = 0
    } else {
      style.transform = `translateY(${visible.value ? '0%' : '100%'})`
      style.bottom = 0
    }
    
  } else if (props.mode === 'center') {
    style.top = 0
    style.left = 0
    style.right = 0
    style.bottom = 0
    if (typeof props?.width !== 'undefined') style.width = handleValueWithUnit(props.width)
    if (typeof props?.height !== 'undefined') style.height = handleValueWithUnit(props.height)
    if (visible.value) {
      style.transform = `scale(1)`
      style.opacity = 1
    } else {
      style.transform = `scale(0)`
      style.opacity = 0
    }
  }
  return Object.assign(style, props?.contentCustomStyle || {})
})
// popupCloseBtn样式
const popupCloseBtnStyle = computed<CSSProperties>(() => {
  let style: CSSProperties = {}
  if (closeIconColor.value.type === 'style') style.color = closeIconColor.value.value
  if (props?.closeIconSize) style.fontSize = handleValueWithUnit(props.closeIconSize)
  return style
})

// popup容器对应的类
const popupClass = computed<string>(() => {
  let clazz: string[] = []
  if (show.value) clazz.push('show')
  return clazz.join(' ')
})
// popup内容对应的类
const popupContentClass = computed<string>(() => {
  let clazz: string[] = []
  if (bgColor.value.type === 'class') clazz.push(bgColor.value.value)
  if (visible.value) clazz.push('visible')
  if (props?.mode) clazz.push(`tn-popup--${props.mode}`)
  if (props?.safeAreaInsetBottom && !['top', 'center'].includes(props.mode)) clazz.push('tn-safe-area-inset-bottom')
  return clazz.join(' ')
})
// popup关闭按钮对应的类
const popupCloseBtnClass = computed<string>(() => {
  let clazz: string[] = []
  if (closeIconColor.value.type === 'class') clazz.push(closeIconColor.value.value)
  if (props?.closeIconPosition) clazz.push(`tn-popup__close--${hump2str(props.closeIconPosition, '-')}`)
  return clazz.join(' ')
})

// maskZIndex值
const maskZIndex = computed<number>(() => {
  if (props?.zIndex) {
    return Number(props.zIndex) - 1
  }
  return 0
})


// 显示组件
let show = ref<boolean>(false)
// 显示内容
let visible = ref<boolean>(false)
// 标记是否内部点击, 防止v-model触发两次
let innerClick = false
// 动画定时器
let statusTimer: number | null

// 控制popup的显示与隐藏
const changePopupStatus = (status: boolean) => {
  resetStatusTimer()
  if (status) {
    show.value = true
    visible.value = true
    emits('open')
  } else {
    visible.value = false
    show.value = false
    emits('close')
    // statusTimer = setTimeout(() => {
    //   resetStatusTimer()
    //   show.value = false
    //   emits('close')
    // }, 250);
  }
  emits(UPDATE_MODEL_EVENT, status)
}
// 重置状态定时器
const resetStatusTimer = () => {
  if (statusTimer) {
    clearTimeout(statusTimer)
    statusTimer = null
  }
}
watch(() => props.modelValue, (val: boolean) => {
  if (val) {
    if (show.value) {
      show.value = false
      return
    }
    changePopupStatus(true)
  } else if(!innerClick) {
    changePopupStatus(false)
  }
  innerClick = false
})

// 关闭popup弹框
const closePopup = (type: 'mask' | 'btn' = 'btn') => {
  if (type === 'mask' && !props?.maskCloseable) return
  innerClick = true
  changePopupStatus(false)
}
</script>

<script lang="ts">
export default {
  options: {
    // 在微信小程序中将组件节点渲染为虚拟节点，更加接近Vue组件的表现(不会出现shadow节点下再去创建元素)
    virtualHost: true
  }
}
</script>

<style lang="scss" scoped>

.tn-popup {
  /* #ifndef APP-NVUE */
  display: block;
  /* #endif */
  visibility: hidden;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  overflow: hidden;

  &.show {
    visibility: visible;
  }

  &__content {
    /* #ifndef APP-NVUE */
    display: block;
    /* #endif */
    position: absolute;
    transition: all 0.25s linear;
    background-color: #FFFFFF;
    overflow: hidden;
  }

  &--center {
    width: fit-content;
    height: fit-content;
    // height: 100%;
    margin: auto;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  &__data {
    width: 100%;
    // height: 100%;
    height: fit-content;
  }

  &__close {
    position: absolute;
    
    &--top-left {
      top: 10rpx;
      left: 10rpx;
    }
    
    &--top-right {
      top: 10rpx;
      right: 10rpx;
    }
    
    &--bottom-left {
      bottom: 10rpx;
      left: 10rpx;
    }
    
    &--bottom-right {
      bottom: 10rpx;
      right: 10rpx;
    }
  }
}
</style>
